//
//  HRTableViewBindingHelper.m
//  HRTableCollectionBindingDemo
//
//  Created by Ran on 14/11/5.
//  Copyright (c) 2014年 Rannie. All rights reserved.
//

#import "KLTableViewBindingHelper.h"
#import "KLTableViewCell.h"


@interface KLTableViewBindingHelper ()
@property (nonatomic, strong) NSString * cellIdentifier;
@property (nonatomic, strong) RACSubject *createCellSubject;

@end

@implementation KLTableViewBindingHelper

#pragma  mark - initialization
// RAC
+ (instancetype)bindingForTableView:(UITableView *)tableView sourceSignal:(RACSignal *)source didSelectionCommand: didSelection templateCell:(UINib *)templateCellNib {
    return [[self alloc] initWithTableView:tableView sourceSignal:source didSelectionCommand:didSelection templateCell:templateCellNib];
}

+ (instancetype)bindingForTableView:(UITableView *)tableView sourceSignal:(RACSignal *)source didSelectionCommand:(RACCommand *)didSelection templateCellClassName:(NSString *)classCell {
    return [[self alloc] initWithTableView:tableView sourceSignal:source didSelectionCommand:didSelection templateCellClassName:classCell];
}

- (instancetype)initWithTableView:(UITableView *)tableView sourceSignal:(RACSignal *)source didSelectionCommand:(RACCommand *)didSelection {
    NSParameterAssert(tableView);
    NSParameterAssert(source);
    self = [super init];
    if (self) {
        _tableView = tableView;
        _data = @[];
        _selectionCommand = didSelection;
        
        [source subscribeNext:^(id x) {
            self->_data = x;
            [self->_tableView reloadData];
        }];
        
        _tableView.dataSource = self;
        _tableView.delegate = self;
    }
    return self;
}

- (instancetype)initWithTableView:(UITableView *)tableView sourceSignal:(RACSignal *)source didSelectionCommand:(RACCommand *)didSelection templateCell:(UINib *)templateCellNib {
    if (self = [self initWithTableView:tableView sourceSignal:source didSelectionCommand:didSelection]) {
        _templateCell = [[templateCellNib instantiateWithOwner:nil options:nil] firstObject];
        [_tableView registerNib:templateCellNib forCellReuseIdentifier:_templateCell.reuseIdentifier];
        _tableView.rowHeight = _templateCell.bounds.size.height;
        
        [self customInitialization];
    }
    return self;
}

- (instancetype)initWithTableView:(UITableView *)tableView sourceSignal:(RACSignal *)source didSelectionCommand:(RACCommand *)didSelection templateCellClassName:(NSString *)classCell {
    if (self = [self initWithTableView:tableView sourceSignal:source didSelectionCommand:didSelection]) {
        self.cellIdentifier = classCell;
        [tableView registerClass:NSClassFromString(classCell) forCellReuseIdentifier:classCell];
        
        [self customInitialization];
    }
    return self;
}

//Normal
+ (instancetype)bindingForTableView:(UITableView *)tableView sourceList:(NSArray *)source didSelectionBlock:(KLTableSelectionBlock)block templateCell:(UINib *)templateCellNib {
    return [[self alloc] initWithTableView:tableView sourceList:source didSelectionBlock:block templateCell:templateCellNib];
}

+ (instancetype)bindingForTableView:(UITableView *)tableView sourceList:(NSArray *)source didSelectionBlock:(KLTableSelectionBlock)block templateCellClassName:(NSString *)templateCellClass {
    return [[self alloc] initWithTableView:tableView sourceList:source didSelectionBlock:block templateCellClassName:templateCellClass];
}

- (instancetype)initWithTableView:(UITableView *)tableView sourceList:(NSArray *)source didSelectionBlock:(KLTableSelectionBlock)block {
    NSParameterAssert(tableView);
    NSParameterAssert(source);
    self = [super init];
    if (self) {
        _tableView = tableView;
        _data = source;
        _selectionBlock = [block copy];
        
        _tableView.dataSource = self;
        _tableView.delegate = self;
    }
    return self;
}

- (instancetype)initWithTableView:(UITableView *)tableView sourceList:(NSArray *)source didSelectionBlock:(KLTableSelectionBlock)block templateCell:(UINib *)templateCellNib {
    self = [self initWithTableView:tableView sourceList:source didSelectionBlock:block];
    if (self) {
        _templateCell = [[templateCellNib instantiateWithOwner:nil options:nil] firstObject];
        [_tableView registerNib:templateCellNib forCellReuseIdentifier:_templateCell.reuseIdentifier];
        _tableView.rowHeight = _templateCell.bounds.size.height;
        
        [self customInitialization];
    }
    return self;
}

- (instancetype)initWithTableView:(UITableView *)tableView sourceList:(NSArray *)source didSelectionBlock:(KLTableSelectionBlock)block templateCellClassName:(NSString *)templateCellClass {
    self = [self initWithTableView:tableView sourceList:source didSelectionBlock:block];
    if (self) {
        self.cellIdentifier = templateCellClass;
        [tableView registerClass:NSClassFromString(templateCellClass) forCellReuseIdentifier:templateCellClass];
        
        [self customInitialization];
    }
    return self;
}

- (void)customInitialization {
    //abstract...
}

- (RACSignal*)createdCellSignal{
    if(!self.createCellSubject){
        self.createCellSubject = [RACSubject subject] ;
    }
    
    return self.createCellSubject;
}

#pragma mark - UITableViewDataSource methods
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView{
    return _useSection?_data.count:(_data.count>0);
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
    return _useSection?(_data.count>0):_data.count;
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    return [self dequeueCellAndBindInTable:tableView indexPath:indexPath];
}
- (NSInteger)indexOfCell:(NSIndexPath*)indexPath{
    return  _useSection?indexPath.section:indexPath.row;
}
- (UITableViewCell *)dequeueCellAndBindInTable:(UITableView *)tableView indexPath:(NSIndexPath *)indexPath {
    KLTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:_templateCell.reuseIdentifier];

    NSAssert([cell isKindOfClass:[KLTableViewCell class]],@"cell not subclass of KLTableViewCell or nil");
    [self.createCellSubject sendNext:RACTuplePack(indexPath,cell)];
    [cell bindViewModel:_data[[self indexOfCell:indexPath]]];
    return cell;
}

#pragma mark - UITableViewDelegate methods
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
    if (_selectionCommand) {
        [_selectionCommand execute:RACTuplePack(indexPath,_data[[self indexOfCell:indexPath]])];
    } else if (_selectionBlock) {
        _selectionBlock(indexPath,_data[[self indexOfCell:indexPath]]);
    }
}

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{
    if (_heightForRowDelegateBlock) {
        return  self.heightForRowDelegateBlock(indexPath);
    }else{
        return 44.0;
    }
}

- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section{
    if (_heightForHeaderBlock) {
        return  self.heightForHeaderBlock(section);
    }else{
        return 0.0;
    }
}

- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section {
    if (_viewForHeaderBlock) {
        return self.viewForHeaderBlock(section);
    }else{
        return nil;
    }
}

- (CGFloat)tableView:(UITableView *)tableView heightForFooterInSection:(NSInteger)section{
    if (_heightForFooterBlock) {
        return  self.heightForFooterBlock(section);
    }else{
        return 0.0;
    }
}

- (UIView *)tableView:(UITableView *)tableView viewForFooterInSection:(NSInteger)section {
    if (_viewForFooterBlock) {
        return self.viewForFooterBlock(section);
    }else{
        return nil;
    }
}

#pragma mark - Action
- (void)reloadDataWithSourceList:(NSArray *)source {
    if (source) {
        _data = source;
    }
    [_tableView reloadData];
}

@end
